﻿using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace OneRed.Data
{
    public class EndNote : IDataTransfrom
    {
        private string author = "";
        private int count = 1;
        private int count_Error = 1;
        public string Transform(string allRecordsTextOriginal)
        {
            string[] integratedLines = Regex.Split(allRecordsTextOriginal, @"\r\n");
            bool isCNKIOld = this.IdentifyCNKI(integratedLines);
            string result;
            if (isCNKIOld)
            {
                System.Text.StringBuilder sb = new System.Text.StringBuilder();
                sb.Append("<?xml version=\"1.0\" standalone=\"yes\" ?>");
                sb.Append("\r\n<!--\r\nFormat=\"EndNote2 (CNKI 旧版)\" \r\nGenerator=\"OneRed\" \r\nCreator=\"vhioner (deep blue rain)\" \r\n-->");
                sb.Append("\r\n<ImptDatas>\r\n");
                sb.Append("\t<TI>数据错误啦！！！</TI>\r\n");
                sb.Append("\t<PY>2015</PY>\r\n");
                sb.Append("\t<SO>SATI</SO>\r\n");
                sb.Append("\t<AB>您输入的EndNote格式题录为CNKI知网旧版，请选择专门针对旧版CNKI EndNote的格式\"EndNote2\"！\r\n原因：新版字段结尾符\"%W\"与作者元数据格式(MultiLine)稍有不同。</AB>\r\n");
                sb.Append("\r\n</ImptDatas>\r\n");
                result = sb.ToString();
            }
            else
            {
                System.Text.StringBuilder sb = new System.Text.StringBuilder();
                sb.Append("<?xml version=\"1.0\" standalone=\"yes\" ?>");
                sb.Append("\r\n<!--\r\nFormat=\"EndNote\" \r\nGenerator=\"OneRed\" \r\nCreator=\"vhioner (deep blue rain)\" \r\n-->");
                sb.Append("\r\n<ImptDatas>\r\n");
                for (int i = 0; i < integratedLines.Length; i++)
                {
                    string line = integratedLines[i];
                    if (line != "" && line.Length > 1)
                    {
                        Regex reg = new Regex(@"(?<type>[\w\W]{2})\s(?<content>[\w\W]*)");
                        string lineHead = reg.Match(line).Groups["type"].ToString();// line.Substring(0, 3);
                        //string text = lineHead;
                        switch (lineHead)
                        {
                            case "  ":
                                if (sb.Length < 1)
                                    break;
                                else
                                {
                                    string stemp = sb.ToString();
                                    string sEnd = "";
                                    if (stemp.LastIndexOf('<') > 0)
                                    {
                                        sEnd = stemp.Substring(stemp.LastIndexOf('<'));
                                        sb.Remove(stemp.LastIndexOf('<'), sEnd.Length);
                                        sb.Append(this.XMLSpecialProcess(line.Substring(2).Trim()) + sEnd);
                                    }
                                    break;
                                }
                            case "%+":
                            case "%I":
                                //string sDanWei = line.Substring(2).Trim().Split(new char[] { ' ', '!' })[0].Replace(';', '|');
                                string sDanWei = line.Substring(2).Trim();
                                sb.Append("\t<AD>" + this.XMLSpecialProcess(ReplaceSeparator(sDanWei)) + "</AD>\r\n");
                                break;
                            case "%T":
                                sb.Append("\t<TI>" + this.XMLSpecialProcess(line.Substring(2).Trim()) + "</TI>\r\n");
                                break;
                            case "%A":
                                this.author += this.XMLSpecialProcess(line.Substring(2).Trim()) + "|";
                                break;
                            case "%J":
                                sb.Append("\t<SO>" + this.XMLSpecialProcess(line.Substring(2).Trim()) + "</SO>\r\n");
                                break;
                            case "%D":
                                sb.Append("\t<PY>" + this.XMLSpecialProcess(line.Substring(2).Trim()) + "</PY>\r\n");
                                break;
                            case "%K":
                                sb.Append("\t<KWs>" + this.XMLSpecialProcess(this.ReplaceSeparator(line.Substring(2))) + "</KWs>\r\n");
                                break;
                            case "%X":
                                sb.Append("\t<AB>" + this.XMLSpecialProcess(line.Substring(2).Trim()) + "</AB>\r\n");
                                break;
                            case "%0":
                                if (this.count < this.count_Error)
                                {
                                    sb.Append("</Bibliography>\r\n");
                                    this.count++;
                                }
                                sb.Append("<Bibliography id=\"" + this.count + "\">\r\n");
                                sb.Append("\t<DT>" + this.XMLSpecialProcess(line.Substring(2).Trim()) + "</DT>\r\n");
                                this.count_Error++;
                                break;
                            case "%W":
                                {
                                    sb.Append("\t<AU>" + this.XMLSpecialProcess(author.TrimEnd('|')) + "</AU>\r\n");
                                    sb.Append("</Bibliography>\r\n");
                                    this.count++;
                                    this.author = "";
                                    break;
                                }
                        }
                    }
                }
                sb.Append("</ImptDatas>");
                result = sb.ToString();
            }
            return result;
        }
        protected string XMLSpecialProcess(string iXML)
        {
            return iXML.Replace("&", "&amp;").Replace("<", "&lt;").Replace(">", "&gt;").Replace("'", "&apos;").Replace("\"", "&quot;");
        }
        protected string RemoveNumber(string inputStr)
        {
            string[] kw = inputStr.Split(new char[]
            {
                '|'
            });
            string temp = "";
            for (int i = 0; i < kw.Length; i++)
            {
                if (this.isNumberic(kw[i].Trim().ToString()))
                {
                    kw[i] = "";
                }
                else
                {
                    temp = temp + kw[i] + "|";
                }
            }
            return temp;
        }
        protected string ReplaceSeparator(string inputStr)
        {
            Dictionary<string, string> dicRgx = new Dictionary<string, string>();
            dicRgx.Add("[;；]+", "|");

            inputStr = RegexReplaceSeparator(inputStr.Trim(), dicRgx);
            return inputStr.TrimEnd('|');
        }
        protected string RegexReplaceSeparator(string sInputStr, Dictionary<string, string> dicRgx)
        {
            foreach (KeyValuePair<string, string> kp in dicRgx)
            {
                if (Regex.IsMatch(sInputStr, kp.Key))
                    sInputStr = Regex.Replace(sInputStr, kp.Key, kp.Value);
            }
            return sInputStr;
        }
        protected bool isNumberic(string message)
        {
            Regex rex = new Regex("^\\d+$");
            bool result2;
            if (rex.IsMatch(message))
            {
                int result = int.Parse(message);
                result2 = true;
            }
            else
            {
                result2 = false;
            }
            return result2;
        }
        protected bool IdentifyCNKI(string[] integratedLines)
        {
            bool isCNKIOld = true;
            for (int i = 0; i < integratedLines.Length; i++)
            {
                string s = integratedLines[i];
                if (s.Length > 6)
                {
                    if (s.Substring(0, 7) == "%W CNKI")
                    {
                        isCNKIOld = false;
                        break;
                    }
                }
            }
            return isCNKIOld;
        }
        protected string[] ReplaceToWCNKI(string[] integratedLines)
        {
            System.Text.StringBuilder sb = new System.Text.StringBuilder();
            for (int i = 0; i < integratedLines.Length; i++)
            {
                string s = integratedLines[i];
                sb.Append(s + '|');
            }
            string originalString = sb.ToString();
            string[] result;
            if (originalString.IndexOf("%W") == -1 && originalString.IndexOf("%@") != -1)
            {
                originalString = originalString.Replace("%@", "%W");
                result = originalString.Split(new char[]
                {
                    '|'
                });
            }
            else
            {
                result = integratedLines;
            }
            return result;
        }
    }
}

